/*
 * @Author: szx
 * @Date: 2022-03-13 16:25:40
 * @LastEditTime: 2022-03-13 16:29:10
 * @Description:
 * @FilePath: \learn\MDN_JS学习\八股文\深浅拷贝\深浅拷贝.js
 */
const shallowCopy = function (obj) {
    // 如果不是对象的话，直接返回
    if (typeof obj !== 'object') return;
    // 根据obj的类型判断是新建一个数组还是对象
    const newObj = obj instanceof Array ? [] : {};
    // 遍历Object.entries，此方法不会遍历原型链上的属性
    for (let [key, value] of Object.entries(obj)) {
        newObj[key] = value;
    }
    return newObj;
};
const orginal = [
    [1, 2],
    [3, 4]
];
const arr = shallowCopy(orginal);
arr[0][0] = 5;
console.log(orginal, arr);

function deepClone(obj, map = new WeakMap()) {
    // 处理 null 和 undefined
    if (obj == null) return obj;

    // 若是基本类型，直接返回
    if (typeof obj !== 'object' && typeof obj !== 'function') return obj;

    // 处理 Date 和 RegExp
    if (obj instanceof Date) return new Date(obj);
    if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags);

    // 使用 map 解决循环引用问题
    if (map.has(obj)) return map.get(obj);

    // 处理函数对象 返回一个新函数，在调用这个函数时会返回原本函数的执行结果
    if (obj instanceof Function) {
        return function () {
            return obj.apply(this, [...arguments]);
        };
    }

    // 下面是 数组/普通对象/Set/Map 的处理

    // 从其原型链中继承的 constructor
    const res = new obj.constructor();

    // 设置 map 以处理循环引用问题
    map.set(obj, res);

    if (obj instanceof Map) {
        obj.forEach((item, index) => {
            // index 不一定是基本数据类型
            res.set(deepClone(index, map), deepClone(item, map));
        });
    } else if (obj instanceof Set) {
        obj.forEach((item) => {
            res.add(deepClone(item, map));
        });
    } else {
        // 使用 Object.entries 不需要再使用 hasOwnProperty 来验证是否是自身属性
        for (let [key, value] of Object.entries(obj)) {
            if (value && typeof value === 'object') {
                res[key] = deepClone(value, map);
            } else {
                res[key] = value;
            }
        }
    }

    return res;
}
